using System;
using System.Collections;
using System.Collections.Generic;
using Main.Event;
using Main.Save;
using Unity.Collections;
using UnityEditor;
using UnityEngine;
using ZSW.Framework;

namespace Main.GameTime
{
    public class TimeManager : ZSWF_Singleton<TimeManager>, ISaveable
    {
        public static TimeSpan GameTime => new TimeSpan(Hour, Minute, Second);

        public string GUID => GetComponent<DataGUID>().guid;

        [ReadOnly] public static int Second;
        [ReadOnly] public static int Minute;
        [ReadOnly] public static int Hour;
        [ReadOnly] public static int Day;
        [ReadOnly] public static int Month;
        [ReadOnly] public static int Year;
        [ReadOnly] public static Season Season;
        private int monthInSeason;
        public bool gameClockPause;
        private float tikTime;

        private float timeDifference;

        public float speed;
        private bool m_loaded;
        public override void Init()
        {
            base.Init();
            // MainEventSystem.InitFinish += NewGameTime;
            MainEventSystem.BeforeLoadSceneEvent += OnBeforeLoadScene;
            MainEventSystem.AfterLoadSceneEvent += OnAfterLoadScene;
            MainEventSystem.UpdateGameStateEvent += OnUpdateGameState;
            MainEventSystem.StartNewGameEvent += OnStartNewGame;
            gameClockPause = true;

            ISaveable saveable = this;
            saveable.RegisterSaveable();
        }

        private void OnStartNewGame(int obj)
        {
            gameClockPause = false;
            NewGameTime();
        }

        private void OnUpdateGameState(GameState state)
        {
            gameClockPause = state == GameState.Pause;
        }

        private void OnAfterLoadScene()
        {
            gameClockPause = false;
            MainEventSystem.CallGameDateEvent(Day, Month, Year, Season);
            MainEventSystem.CallGameDayEvent(Second, Minute, Hour, Day, Season);
            MainEventSystem.CallLightShiftChange(Season, GetCurrentLightShift(), timeDifference);
        }

        private void OnBeforeLoadScene()
        {
            gameClockPause = true;
        }

        private void NewGameTime()
        {
            if (m_loaded)
            {
                return;
            }

            m_loaded = true;
            Second = 0;
            Minute = 0;
            Hour = 7;
            Day = 1;
            Month = 1;
            Year = 1;
            MainEventSystem.CallGameDateEvent(Day, Month, Year, Season);
            MainEventSystem.CallGameDayEvent(Second, Minute, Hour, Day, Season);
            MainEventSystem.CallLightShiftChange(Season, GetCurrentLightShift(), timeDifference);
            Debug.Log($"初始化时间完成");
        }

        private void Update()
        {
            if (Input.GetKey(KeyCode.T))
            {
                speed = 100;
            }
            else
            {
                speed = 1;
            }

            if (Input.GetKeyDown(KeyCode.G))
            {
                Day++;
                MainEventSystem.CallGameDateEvent(Day, Month, Year, Season);
            }

            if (!gameClockPause)
            {
                tikTime += Time.deltaTime;
                if (tikTime >= Settings.secondThreshold)
                {
                    for (int i = 0; i < speed; i++)
                    {
                        UpdateGameTime();
                    }
                    tikTime -= Settings.secondThreshold;
                }
            }
        }

        private void UpdateGameTime()
        {
            Second++;
            if (Second > Settings.SecondHold)
            {
                Second = 0;
                Minute++;
                if (Minute > Settings.MinuteHold)
                {
                    Minute = 0;
                    Hour++;
                    if (Hour > Settings.HourHold)
                    {
                        Hour = 0;
                        Day++;
                        if (Day > Settings.DayHold)
                        {
                            Day = 1;
                            Month++;
                            if (Month > 12)
                            {
                                Month = 1;
                            }

                            monthInSeason--;
                            if (monthInSeason == 0)
                            {
                                monthInSeason = 3;

                                int seasonNumber = (int)Season++;

                                if (seasonNumber > Settings.SeasonHold)
                                {
                                    seasonNumber = 0;

                                    Year++;
                                }

                                Season = (Season)seasonNumber;
                            }
                        }

                        MainEventSystem.CallGameDateEvent(Day, Month, Year, Season);
                    }
                }

                MainEventSystem.CallGameDayEvent(Second, Minute, Hour, Day, Season);

                MainEventSystem.CallLightShiftChange(Season, GetCurrentLightShift(), timeDifference);
            }
        }

        private LightShift GetCurrentLightShift()
        {
            if (GameTime >= Settings.morningTime && GameTime <= Settings.nightTime)
            {
                timeDifference = (float)(GameTime - Settings.morningTime).TotalMinutes;
                return LightShift.Morning;
            }

            if (GameTime < Settings.morningTime || GameTime > Settings.nightTime)
            {
                timeDifference = Mathf.Abs((float)(GameTime - Settings.nightTime).TotalMinutes);

                return LightShift.Night;
            }

            return LightShift.Morning;
        }

        public GameSaveData GenerateSaveData()
        {
            return new GameSaveData
            {
                timeDict = new Dictionary<string, int>()
                {
                    { "Second", Second },
                    { "Minute", Minute },
                    { "Hour", Hour },
                    { "Day", Day },
                    { "Month", Month },
                    { "Year", Year },
                    { "Season", (int)Season }
                }
            };
        }

        public void RestoreData(GameSaveData data)
        {
            Second = data.timeDict["Second"];
            Minute = data.timeDict["Minute"];
            Hour = data.timeDict["Hour"];
            Day = data.timeDict["Day"];
            Month = data.timeDict["Month"];
            Year = data.timeDict["Year"];
            Season = (Season)data.timeDict["Season"];
        }
    }


}